{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f05fe33e-ecff-460c-8542-8ece3d2d0158",
   "metadata": {},
   "source": [
    "# Using TensorRT-LLM and StreamingLLM for Efficient Inference on Mistral"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14dcb6c1-907e-4ecd-bc00-1f51c42c5655",
   "metadata": {},
   "source": [
    "Welcome!\n",
    "\n",
    "In this notebook, we will walk through using the StreamingLLM framework to run inference on Mistral. TensorRT-LLM provides users with an easy-to-use Python API to define Large Language Models (LLMs) and build TensorRT engines that contain state-of-the-art optimizations to perform inference efficiently on NVIDIA GPUs. StreamingLLM is a novel framework developed at the MIT-Han-Lab and is supported in TensorRT-LLM. See the [Github repo](\"https://github.com/mit-han-lab/streaming-llm\") for more examples and documentation!\n",
    "\n",
    "#### Introduction to StreamingLLM\n",
    "Handling infinite-length text with LLMs presents challenges. Notably, storing all previous Key and Value (KV) states demands significant memory, and models might struggle to generate text beyond their training sequence length.  StreamingLLM addresses this by retaining only the most recent tokens and attention sinks, discarding intermediate tokens. This enables the model to generate coherent text from recent tokens without a cache reset — a capability not seen in earlier methods.\n",
    "\n",
    "StreamingLLM is optimized for streaming applications, such as multi-round dialogues. It's ideal for scenarios where a model needs to operate continually without requiring extensive memory or dependency on past data. An example is a daily assistant based on LLMs. StreamingLLM would let the model function continuously, basing its responses on recent conversations without needing to refresh its cache. Earlier methods would either need a cache reset when the conversation length exceeded the training length (losing recent context) or recompute KV states from recent text history, which can be time-consuming."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a968b71-06cd-4ff3-b470-81314214f688",
   "metadata": {},
   "source": [
    "![streamingllm](https://www.kdnuggets.com/wp-content/uploads/wijaya_introduction_streamingllm_llms_infinitelength_inputs_1.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec18e04e-5154-44bb-b4a9-c4f6053f590c",
   "metadata": {},
   "source": [
    "#### Credits\n",
    "Professor Song Han is an NVIDIA Distinguished Engineer and an associate professor in the MIT EECS department. He has been credited for numerous advances in the field of deep learning and has founded multiple AI companies.\n",
    "\n",
    "Deployment powered by Brev.dev 🤙"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60738f0c-fc5c-4400-8785-1f947c53d3b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0db06ad6-9a07-4229-ae3c-f90cd60e9bba",
   "metadata": {},
   "source": [
    "#### Install TensorRT-LLM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "126af5bb-9f42-4de7-9e75-b2b8a91cc007",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q ipywidgets\n",
    "!pip install \"tensorrt_llm==0.8.0\" -U --extra-index-url https://pypi.nvidia.com"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93b55b74-b7d4-4ba9-8096-1e678d93417e",
   "metadata": {},
   "outputs": [],
   "source": [
    "!wget https://raw.githubusercontent.com/NVIDIA/TensorRT-LLM/main/tensorrt_llm/models/llama/convert.py\n",
    "!mv convert.py /usr/local/lib/python3.10/dist-packages/tensorrt_llm/models/llama/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08e09d07-0a25-4f48-8da1-5893c3d6951e",
   "metadata": {},
   "outputs": [],
   "source": [
    "!wget https://raw.githubusercontent.com/NVIDIA/TensorRT-LLM/rel/examples/llama/convert_checkpoint.py -P .\n",
    "!wget https://raw.githubusercontent.com/NVIDIA/TensorRT-LLM/rel/examples/run.py -P .\n",
    "!wget https://raw.githubusercontent.com/NVIDIA/TensorRT-LLM/rel/examples/utils.py -P ."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "194dc615-f8ae-42ec-8b5d-79c01d4183d7",
   "metadata": {},
   "source": [
    "### Convert Mistral to the TensorRT format\n",
    "\n",
    "For StreamingLLM to be enabled, we pass two additional flags to the checkpoint conversion\n",
    "\n",
    "- `dense_context_fmha` - uses dense context fmha in the context phase\n",
    "- `enable_pos_shift` - lets us use positions in KV cache for RoPE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95cfc8eb-bfc5-4872-9a94-ccde2953175e",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Build the model with StreamingLLM feature using a single GPU and FP16.\n",
    "!python convert_checkpoint.py --model_dir mistralai/Mistral-7B-v0.1 \\\n",
    "    --output_dir ./tllm_checkpoint_1gpu_streamingllm \\\n",
    "    --dtype float16 \\\n",
    "    --dense_context_fmha \\\n",
    "    --enable_pos_shift"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "798ee3d8-4a76-40eb-9e92-b63480074aae",
   "metadata": {},
   "source": [
    "### Build the TensorRT engine for the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a14b6b3f-b86f-4ed5-b53a-ac58f563c5bb",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "zsh:1: command not found: trtllm-build\n"
     ]
    }
   ],
   "source": [
    "# Streaming \n",
    "!trtllm-build --checkpoint_dir ./tllm_checkpoint_1gpu_streamingllm \\\n",
    "    --output_dir ./mistralengine_streaming \\\n",
    "    --gemm_plugin float16"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a12000e-4b0d-4e47-ba55-e84792774d23",
   "metadata": {},
   "source": [
    "### Run inference with a large input sequence \n",
    "\n",
    "We use an open source Shakesphere dataset to demonstrate. We use 125,000 characters as our input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "bc710018-6450-4676-a97b-bef1f7d0ae3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import re\n",
    "\n",
    "url = 'https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt'\n",
    "\n",
    "response = requests.get(url)\n",
    "\n",
    "if response.status_code == 200:\n",
    "    story = response.text\n",
    "    story = re.sub('\\s+', ' ', story).strip()\n",
    "else:\n",
    "    story = None\n",
    "    print(\"Failed to retrieve the document.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acbf11ff-9d89-432b-a622-daa44c6b1a19",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time \n",
    "\n",
    "# Use the streaming engine with a sliding window/cache size 2048 and sink token length 4 \n",
    "!python3 ./run.py --max_output_len=150 \\\n",
    "                  --tokenizer_dir mistralai/Mistral-7B-v0.1 \\\n",
    "                  --engine_dir=./mistralengine_streaming \\\n",
    "                  --max_attention_window_size=4096 \\\n",
    "                  --sink_token_length=4 \\\n",
    "                  --input_text f\"{story[983152:]}\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
